package dongze.com.ckdj.adapter;

import android.content.res.Resources;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.databinding.DataBindingUtil;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListAdapter;
import android.widget.TextView;

import java.io.File;
import java.lang.ref.SoftReference;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import dongze.com.ckdj.R;
import dongze.com.ckdj.activity.ImageUploadActivity;
import dongze.com.ckdj.databinding.Action;
import dongze.com.ckdj.databinding.ImageUploadListItemBinding;
import dongze.com.ckdj.databinding.model.ImageUploadListItemModel;
import dongze.com.ckdj.persistence.dao.DaoSession;
import dongze.com.ckdj.persistence.dao.MassLossUploadRecord;
import dongze.com.ckdj.persistence.dao.MassLossUploadRecordDao;
import dongze.com.ckdj.persistence.dao.NamePlateUploadRecord;
import dongze.com.ckdj.persistence.dao.NamePlateUploadRecordDao;
import dongze.com.ckdj.persistence.dao.State;
import dongze.com.ckdj.service.ImageUploadTask;
import dongze.com.ckdj.service.uploader.UploaderFactory;
import dongze.com.ckdj.util.Util;

/**
 * Created by fanqwz on 2017/8/7.
 */

public class ImageUploadListAdapter implements ExpandableListAdapter {
    private static final String TAG = ImageUploadListAdapter.class.getSimpleName();
    private String[] groups = new String[]{"未上传", "正在上传", "已完成"};
    private List<ImageListItem> uploading;
    private List<ImageListItem> unStart;
    private List<ImageListItem> finished;
    private DataSetObservable observable;
    private ImageUploadActivity.IImageUploadAction action;
    private static Map<String, SoftReference<Drawable>> drawableCache = new HashMap<>();
    private Resources res;
    private DaoSession session;

    public ImageUploadListAdapter(List<ImageListItem> uploading,
                                  List<ImageListItem> unStart,
                                  List<ImageListItem> finished,
                                  DataSetObservable observable,
                                  ImageUploadActivity.IImageUploadAction action,
                                  Resources res,
                                  DaoSession session) {
        this.uploading = uploading;
        this.unStart = unStart;
        this.finished = finished;
        this.observable = observable;
        this.action = action;
        this.res = res;
        this.session = session;
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        observable.registerObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        observable.unregisterObserver(observer);
    }

    @Override
    public int getGroupCount() {
        return 3;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        switch (groupPosition) {
            case 0:
                return unStart == null ? 0 : unStart.size();

            case 1:
                return uploading == null ? 0 : uploading.size();

            case 2:
                return finished == null ? 0 : finished.size();
        }

        return 0;
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groups[groupPosition];
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        switch (groupPosition) {
            case 0:
                return unStart.get(childPosition);
            case 1:
                return uploading.get(childPosition);
            case 2:
                return finished.get(childPosition);
        }

        return null;
    }

    @Override
    public long getGroupId(int groupPosition) {
        return 0;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return 0;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_upload_list_group, parent, false);
        }

        TextView textView = (TextView) convertView.findViewById(android.R.id.text1);
        textView.setText(groups[groupPosition] + " (" + getChildrenCount(groupPosition) + ")");
        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        if (convertView == null) {
            ImageUploadListItemBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.image_upload_list_item, null, false);
            binding.setTask(new ImageUploadListItemModel());
            convertView = binding.getRoot();
            convertView.setTag(binding.getTask());
        }

        ImageUploadListItemModel model = (ImageUploadListItemModel) convertView.getTag();
        ((ImageListItem) getChild(groupPosition, childPosition)).bind(convertView.getResources(), model);


        switch (((ImageListItem) getChild(groupPosition, childPosition)).getTask().getState()) {
            case INIT:
                updateStateInit(((ImageListItem) getChild(groupPosition, childPosition)).getTask(), model);
                break;
            case Undefined:
                updateStateUnDefined(((ImageListItem) getChild(groupPosition, childPosition)).getTask(), model);
                break;
            case QUEUED:
            case Waiting:
            case Uploading:
                updateStateUploading(((ImageListItem) getChild(groupPosition, childPosition)).getTask(), model);
                break;
            case Finished:
                updateStateFinished(((ImageListItem) getChild(groupPosition, childPosition)).getTask(), model);
                break;
        }

        return convertView;
    }

    private void updateStateInit(final ImageUploadTask task, final ImageUploadListItemModel imageUploadListItemModel) {
        imageUploadListItemModel.setAction(new Action("启动", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                action.restart(task.getId());
            }
        }));
    }

    private void updateStateUnDefined(final ImageUploadTask task, final ImageUploadListItemModel imageUploadListItemModel) {
        imageUploadListItemModel.setAction(new Action("重新启动", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                action.restart(task.getId());
            }
        }));
    }

    private void updateStateUploading(final ImageUploadTask task, final ImageUploadListItemModel imageUploadListItemModel) {
        imageUploadListItemModel.setAction(null);
    }

    private void updateStateFinished(final ImageUploadTask task, final ImageUploadListItemModel imageUploadListItemModel) {
        imageUploadListItemModel.setAction(new Action("删除", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                action.delete(task.getId());
            }
        }));
    }

//    private static void getDrawable(final Resources res, final String path, final ObservableField<Drawable> drawableObservableField) {
//        if (drawableCache.get(path) != null &&
//                drawableCache.get(path).get() != null) {
//            drawableObservableField.set(drawableCache.get(path).get());
//            return;
//        }
//
//        drawableObservableField.set(null);
//        Observable.create(new ObservableOnSubscribe<Drawable>() {
//            @Override
//            public void subscribe(ObservableEmitter<Drawable> e) throws Exception {
//                try {
//                    BitmapFactory.Options options = new BitmapFactory.Options();
//                    options.inSampleSize = 2;
//                    Bitmap b = BitmapFactory.decodeFile(path, options);
//                    Drawable d = new BitmapDrawable(res, b);
//                    drawableCache.put(path, new SoftReference<>(d));
//                    e.onNext(d);
//                    e.onComplete();
//                } catch (Exception ex) {
//                    MyLog.e(TAG, "subscribe: ", ex);
////                        e.onError(ex);
//                    e.onNext(res.getDrawable(R.mipmap.ic_launcher));
//                    e.onComplete();
//                }
//
//            }
//        }).subscribeOn(Schedulers.io())
//                .subscribeWith(new Observer<Drawable>() {
//                    @Override
//                    public void onSubscribe(Disposable d) {
//
//                    }
//
//                    @Override
//                    public void onNext(Drawable value) {
//                        drawableObservableField.set(value);
//                    }
//
//                    @Override
//                    public void onError(Throwable e) {
//
//                    }
//
//                    @Override
//                    public void onComplete() {
//
//                    }
//                });
//    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public void onGroupExpanded(int groupPosition) {

    }

    @Override
    public void onGroupCollapsed(int groupPosition) {

    }

    @Override
    public long getCombinedChildId(long groupId, long childId) {
        return 0;
    }

    @Override
    public long getCombinedGroupId(long groupId) {
        return 0;
    }

    public static ImageListItem createImageListItem(ImageUploadTask task, DaoSession daoSession) {
        if (UploaderFactory.TYPE_MASS_LOSS.equals(task.getType()))
            return new MassLossRecordItem(task, daoSession);
        else if (UploaderFactory.TYPE_NAME_PLATE.equals(task.getType())
                || UploaderFactory.TYPE_OUT_LINE.equals(task.getType())
                || UploaderFactory.TYPE_IMAGE.equals(task.getType())
                || UploaderFactory.TYPE_RANDOM_INSPECTION.equals(task.getType()))
            return new NamePlateRecordItem(task, daoSession);

        return null;
    }

    private static String getStateText(State state) {
        switch (state) {
            case INIT:
                return "待处理";
            case QUEUED:
                return "排队中";
            case Waiting:
                return "等待上传";
            case Uploading:
                return "正在上传";
            case Finished:
                return "上传完成";
            case Undefined:
                return "上传失败";
            default:
                return "未知状态";
        }
    }

    public static class MassLossRecordItem extends ImageListItem<MassLossUploadRecord> {

        public MassLossRecordItem(ImageUploadTask task, DaoSession session) {
            super(task);
            record = session.getMassLossUploadRecordDao().queryBuilder().where(MassLossUploadRecordDao.Properties.Id.eq(task.getRecordId())).unique();
        }

        @Override
        public void bind(Resources res, ImageUploadListItemModel model) {
            model.vin.set(record.getVin());
            model.state.set(getStateText(task.getState()));
            if (task.getState() == State.Uploading)
                model.progress.set(task.getUploadProgress());
            else
                model.progress.set(-1);
            model.type.set(UploaderFactory.getTypeText(task.getType()));
            model.user.set(record.getUser());
            model.detail.set(record.getImageIndex());
            model.time.set(new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(record.getTime()));
            model.img.set(record.getImagePath());
//            getDrawable(res, record.getImagePath(), model.img);
            model.viewImage.set(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    try {
                        Util.ViewImage(v.getContext(), new File(record.getImagePath()));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    public static class NamePlateRecordItem extends ImageListItem<NamePlateUploadRecord> {

        public NamePlateRecordItem(ImageUploadTask task, DaoSession session) {
            super(task);
            record = session.getNamePlateUploadRecordDao().queryBuilder().where(NamePlateUploadRecordDao.Properties.Id.eq(task.getRecordId())).unique();
        }

        @Override
        public void bind(Resources res, ImageUploadListItemModel model) {
            model.vin.set(record.getVin());
            model.state.set(getStateText(task.getState()));
            if (task.getState() == State.Uploading)
                model.progress.set(task.getUploadProgress());
            else
                model.progress.set(-1);
            model.type.set(UploaderFactory.getTypeText(task.getType()));
            model.user.set(record.getUser());
            model.detail.set(null);
            model.time.set(new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(record.getTime()));
//            getDrawable(res, record.getImagePath(), model.img);
            model.img.set(record.getImagePath());
            model.viewImage.set(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    try {
                        Util.ViewImage(v.getContext(), new File(record.getImagePath()));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    public static abstract class ImageListItem<T> {
        final ImageUploadTask task;
        T record;

        public ImageListItem(ImageUploadTask task) {
            this.task = task;
        }

        public ImageUploadTask getTask() {
            return task;
        }

        public T getRecord() {
            return record;
        }

        abstract public void bind(Resources res, ImageUploadListItemModel model);
    }
}
